﻿using NPOI;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using Star.Tools.Excel.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Star.Tools.Excel
{
    public static partial class SheetExtensions
    {
        #region 1.0 添加条件格式规则

        /// <summary>
        ///     添加条件格式规则
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="cfrs">条件格式规则</param>
        public static void AddConditionalFormattingRules(this ICell cell, IConditionalFormattingRule[] cfrs)
        {
            CellRangeAddress[] regions =
            {
                new CellRangeAddress(cell.RowIndex, cell.RowIndex, cell.ColumnIndex, cell.ColumnIndex)
            };
            cell.Sheet.SheetConditionalFormatting.AddConditionalFormatting(regions, cfrs);
        }

        #endregion

        #region 1.1 获取条件格式规则

        /// <summary>
        ///     获取条件格式规则
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        public static IConditionalFormattingRule[] GetConditionalFormattingRules(this ICell cell)
        {
            var cfrList = new List<IConditionalFormattingRule>();

            ISheetConditionalFormatting scf = cell.Sheet.SheetConditionalFormatting;
            for (int i = 0; i < scf.NumConditionalFormattings; i++)
            {
                IConditionalFormatting cf = scf.GetConditionalFormattingAt(i);
                if (cell.ExistConditionalFormatting(cf))
                {
                    for (int j = 0; j < cf.NumberOfRules; j++)
                    {
                        cfrList.Add(cf.GetRule(j));
                    }
                }
            }
            return cfrList.ToArray();
        }

        #endregion

        #region 3.0 判断单元格是否存在条件格式

        /// <summary>
        ///     单元格是否存在条件格式
        /// </summary>
        /// <param name="cell">单元格</param>
        /// <param name="cf">条件格式</param>
        /// <returns></returns>
        private static bool ExistConditionalFormatting(this ICell cell, IConditionalFormatting cf)
        {
            CellRangeAddress[] cfRangeAddrs = cf.GetFormattingRanges();
            foreach (CellRangeAddress cfRangeAddr in cfRangeAddrs)
            {
                if (cell.RowIndex >= cfRangeAddr.FirstRow && cell.RowIndex <= cfRangeAddr.LastRow
                    && cell.ColumnIndex >= cfRangeAddr.FirstColumn && cell.ColumnIndex <= cfRangeAddr.LastColumn)
                {
                    return true;
                }
            }
            return false;
        }

        #endregion

        #region 行扩展操作
        #region 插入行

        /// <summary>
        ///     插入行
        /// </summary>
        /// <param name="sheet">要插入行的sheet</param>
        /// <param name="rowIndex">行标</param>
        /// <returns></returns>
        public static IRow InsertRow(this ISheet sheet, int rowIndex)
        {
            return sheet.InsertRows(rowIndex, 1)[0];
        }

        /// <summary>
        ///     插入行
        /// </summary>
        /// <param name="sheet">要插入行的sheet</param>
        /// <param name="rowIndex">行标</param>
        /// <param name="rowsCount">行数</param>
        /// <returns></returns>
        public static IRow[] InsertRows(this ISheet sheet, int rowIndex, int rowsCount)
        {
            if (rowIndex <= sheet.LastRowNum)
            {
                sheet.ShiftRows(rowIndex, sheet.LastRowNum, rowsCount, true, false);
            }

            var rowList = new List<IRow>();
            for (int i = 0; i < rowsCount; i++)
            {
                IRow row = sheet.CreateRow(rowIndex + i);
            }
            sheet.MovePictures(rowIndex, null, null, null, moveRowCount: rowsCount);
            return rowList.ToArray();
        }

        /// <summary>插入行</summary>
        /// <param name="sheet">要插入行的sheet</param>
        /// <param name="startindex">从这一行的前面插入(这一行开始包括这一行都会被整体向下移动rowcount)</param>
        /// <param name="rowcount">插入的行数</param>
        /// <param name="stylerow">被插入行采用的样式行的索引,注意这个索引行所在的位置应该位于插入起始行之上</param>
        public static void InsertRow(ISheet sheet, int startindex, int rowcount, int styleindex)
        {
            IRow stylerow = sheet.GetRow(styleindex);
            if (sheet.LastRowNum >= startindex)
            {
                //批量移动行
                sheet.ShiftRows(startindex, sheet.LastRowNum, rowcount, true/*是否复制行高*/, false);
            }

            #region 对批量移动后空出的空行插，创建相应的行，并以样式行作为模板设置样式
            for (int i = startindex; i < startindex + rowcount; i++)
            {
                IRow targetRow = null;
                ICell sourceCell = null;
                ICell targetCell = null;

                targetRow = sheet.CreateRow(i);
                targetRow.Height = stylerow.Height;
                targetRow.HeightInPoints = stylerow.HeightInPoints;
                targetRow.ZeroHeight = stylerow.ZeroHeight;

                int mergeindex = -1;
                for (int m = stylerow.FirstCellNum; m < stylerow.LastCellNum; m++)
                {
                    sourceCell = stylerow.GetCell(m);
                    if (sourceCell == null)
                    {
                        if (mergeindex > 0)
                        {
                            sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(i, i, mergeindex, m));
                            mergeindex = -1;
                        }
                        continue;
                    }


                    targetCell = targetRow.CreateCell(m);

                    targetCell.CellStyle = sourceCell.CellStyle;
                    targetCell.SetCellType(sourceCell.CellType);
                    if (sourceCell.IsMergedCell)
                    {
                        if (mergeindex > 0 && m + 1 < stylerow.LastCellNum)
                        {
                            continue;
                        }
                        else if (mergeindex > 0 && m + 1 == stylerow.LastCellNum)
                        {
                            sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(i, i, mergeindex, m));
                            mergeindex = -1;
                        }
                        else
                        {
                            mergeindex = m;
                        }
                    }
                    else
                    {
                        if (mergeindex > 0)
                        {
                            sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(i, i, mergeindex, m));
                            mergeindex = -1;
                        }
                    }
                }
            }

            IRow firstTargetRow = sheet.GetRow(startindex);
            ICell firstSourceCell = null;
            ICell firstTargetCell = null;
            if (rowcount > 0)
            {
                //新添加的行应用样式
                for (int m = stylerow.FirstCellNum; m < stylerow.LastCellNum; m++)
                {
                    firstSourceCell = stylerow.GetCell(m);
                    if (firstSourceCell == null)
                        continue;
                    firstTargetCell = firstTargetRow.CreateCell(m);

                    firstTargetCell.CellStyle = firstSourceCell.CellStyle;
                    firstTargetCell.SetCellType(firstSourceCell.CellType);
                }
            }
            #endregion
        }
        #endregion

        #region 删除行

        /// <summary>
        ///     删除行
        /// </summary>
        /// <param name="sheet">要删除行的sheet</param>
        /// <param name="rowIndex">行标</param>
        public static int RemoveRow(this ISheet sheet, int rowIndex)
        {
            return sheet.RemoveRows(rowIndex, rowIndex);
        }

        /// <summary>
        ///     删除行
        /// </summary>
        /// <param name="sheet">要删除行的sheet</param>
        /// <param name="startRowIndex">开始行行标</param>
        /// <param name="endRowIndex">结束行行标</param>
        public static int RemoveRows(this ISheet sheet, int startRowIndex, int endRowIndex)
        {
            int span = endRowIndex - startRowIndex + 1;
            //删除合并区域...
            sheet.RemoveMergedRegions(startRowIndex, endRowIndex, null, null);
            //删除图片...
            sheet.RemovePictures(startRowIndex, endRowIndex, null, null);
            //删除行
            for (int i = endRowIndex; i >= startRowIndex; i--)
            {
                IRow row = sheet.GetRow(i);
                sheet.RemoveRow(row);
            }
            if ((endRowIndex + 1) <= sheet.LastRowNum)
            {
                sheet.ShiftRows((endRowIndex + 1), sheet.LastRowNum, -span, true, false);
                sheet.MovePictures(endRowIndex + 1, null, null, null, moveRowCount: -span);
            }
            return span;
        }

        #endregion

        #region 复制行

        /// <summary>
        ///     复制行
        /// </summary>
        /// <param name="sheet">要复制行的sheet</param>
        /// <param name="rowIndex">行标</param>
        public static int CopyRow(this ISheet sheet, int rowIndex)
        {
            return sheet.CopyRows(rowIndex, rowIndex);
        }

        /// <summary>
        ///     复制行
        /// </summary>
        /// <param name="sheet">要复制行的sheet</param>
        /// <param name="startRowIndex">开始行行标</param>
        /// <param name="endRowIndex">结束行行标</param>
        public static int CopyRows(this ISheet sheet, int startRowIndex, int endRowIndex)
        {
            int span = endRowIndex - startRowIndex + 1;

            int newStartRowIndex = startRowIndex + span;
            //插入空行
            sheet.InsertRows(newStartRowIndex, span);
            //复制行
            for (int i = startRowIndex; i <= endRowIndex; i++)
            {
                IRow sourceRow = sheet.GetRow(i);
                IRow targetRow = sheet.GetRow(i + span);

                targetRow.Height = sourceRow.Height;
                targetRow.ZeroHeight = sourceRow.ZeroHeight;

                #region 复制单元格

                foreach (ICell sourceCell in sourceRow.Cells)
                {
                    ICell targetCell = targetRow.GetCell(sourceCell.ColumnIndex);
                    if (null == targetCell)
                    {
                        targetCell = targetRow.CreateCell(sourceCell.ColumnIndex);
                    }
                    if (null != sourceCell.CellStyle) targetCell.CellStyle = sourceCell.CellStyle;
                    if (null != sourceCell.CellComment) targetCell.CellComment = sourceCell.CellComment;
                    if (null != sourceCell.Hyperlink) targetCell.Hyperlink = sourceCell.Hyperlink;
                    IConditionalFormattingRule[] cfrs = sourceCell.GetConditionalFormattingRules(); //复制条件样式
                    if (null != cfrs && cfrs.Length > 0)
                    {
                        targetCell.AddConditionalFormattingRules(cfrs);
                    }
                    targetCell.SetCellType(sourceCell.CellType);

                    #region 复制值

                    switch (sourceCell.CellType)
                    {
                        case CellType.Numeric:
                            targetCell.SetCellValue(sourceCell.NumericCellValue);
                            break;
                        case CellType.String:
                            targetCell.SetCellValue(sourceCell.RichStringCellValue);
                            break;
                        case CellType.Formula:
                            targetCell.SetCellFormula(sourceCell.CellFormula);
                            break;
                        case CellType.Blank:
                            targetCell.SetCellValue(sourceCell.StringCellValue);
                            break;
                        case CellType.Boolean:
                            targetCell.SetCellValue(sourceCell.BooleanCellValue);
                            break;
                        case CellType.Error:
                            targetCell.SetCellErrorValue(sourceCell.ErrorCellValue);
                            break;
                    }

                    #endregion
                }

                #endregion
            }
            //获取模板行内的合并区域
            List<MergedRegionInfo> regionInfoList = sheet.GetMergedRegionInfos(startRowIndex, endRowIndex, null,  null);
            //复制合并区域
            foreach (MergedRegionInfo regionInfo in regionInfoList)
            {
                regionInfo.FirstRow += span;
                regionInfo.LastRow += span;
                CellExtensions.AddMergedRegion(sheet,regionInfo);
            }
            //获取模板行内的图片
            List<PictureInfo> picInfoList = sheet.GetAllPictureInfos(startRowIndex, endRowIndex, null, null);
            //复制图片
            foreach (PictureInfo picInfo in picInfoList)
            {
                picInfo.MaxRow += span;
                picInfo.MinRow += span;
                sheet.AddPicture(picInfo);
            }

            return span;
        }

        #endregion
        #endregion


        #region 获取合并区域信息

        /// <summary>
        ///     获取sheet中包含合并区域的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <returns></returns>
        public static List<MergedRegionInfo> GetMergedRegionInfos(this ISheet sheet)
        {
            return GetMergedRegionInfos(sheet, null, null, null, null);
        }

        /// <summary>
        ///获取sheet中指定区域包含合并区域的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <returns></returns>
        public static List<MergedRegionInfo> GetMergedRegionInfos(this ISheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol)
        {
            var regionInfoList = new List<MergedRegionInfo>();
            for (int i = 0; i < sheet.NumMergedRegions; i++)
            {
                CellRangeAddress range = sheet.GetMergedRegion(i);
                if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, range.FirstRow, range.LastRow,
                    range.FirstColumn, range.LastColumn, true))
                {
                    regionInfoList.Add(new MergedRegionInfo(i, range.FirstRow, range.LastRow, range.FirstColumn,
                        range.LastColumn));
                }
            }
            return regionInfoList;
        }
        /// <summary>
        /// 从工作薄中获取指定范围的图形对象列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="rangeMinRow"></param>
        /// <param name="rangeMaxRow"></param>
        /// <param name="rangeMinCol"></param>
        /// <param name="rangeMaxCol"></param>
        /// <returns></returns>
        public static List<object> GetShapesFromSheet(ISheet sheet, int? rangeMinRow = null, int? rangeMaxRow = null, int? rangeMinCol = null, int? rangeMaxCol = null)
        {
            List<object> shapeAllList = new List<object>();
            var shapeContainer = sheet.DrawingPatriarch;
            if (sheet is HSSFSheet)
            {
                var shapeContainerHSSF = sheet.DrawingPatriarch as HSSFShapeContainer;
                if (null != shapeContainer)
                {
                    var shapeList = shapeContainerHSSF.Children;
                    foreach (var shape in shapeList)
                    {
                        if (shape is HSSFShape && shape.Anchor is HSSFClientAnchor)
                        {
                            var anchor = shape.Anchor as HSSFClientAnchor;
                            if (CellExtensions.IsInternalOrIntersect(rangeMinRow, rangeMaxRow, rangeMinCol, rangeMaxCol, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, true))
                            {
                                shapeAllList.Add(shape);
                            }
                        }
                    }
                }
            }
            else
            {
                var documentPartList = (sheet as XSSFSheet).GetRelations();
                foreach (var documentPart in documentPartList)
                {
                    if (documentPart is XSSFDrawing)
                    {
                        var drawing = (XSSFDrawing)documentPart;
                        var shapeList = drawing.GetShapes();
                        foreach (var shape in shapeList)
                        {
                            var anchorResult = shape.GetAnchor();
                            if (shape is XSSFShape && anchorResult is XSSFClientAnchor)
                            {
                                var anchor = anchorResult as XSSFClientAnchor;
                                if (CellExtensions.IsInternalOrIntersect(rangeMinRow, rangeMaxRow, rangeMinCol, rangeMaxCol, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, true))
                                {
                                    shapeAllList.Add(shape);
                                }
                            }
                        }
                    }
                }
            }

            return shapeAllList;
        }


        #endregion

        #region  删除合并区域

        /// <summary>
        ///     删除合并区域
        /// </summary>
        /// <param name="sheet"></param>
        public static void RemoveMergedRegions(this ISheet sheet)
        {
            sheet.RemoveMergedRegions(null, null, null, null);
        }

        /// <summary>
        ///     删除指定区域内的合并区域
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        public static void RemoveMergedRegions(this ISheet sheet, int? minRow, int? maxRow,
            int? minCol, int? maxCol)
        {
            List<MergedRegionInfo> regionInfoList;
            do
            {
                regionInfoList = GetMergedRegionInfos(sheet,minRow, maxRow, minCol, maxCol);
                foreach (MergedRegionInfo regionInfo in regionInfoList)
                {
                    sheet.RemoveMergedRegion(regionInfo.Index);
                }
            } while (regionInfoList.Count > 0);
        }

        #endregion


        #region 移动合并区域

        /// <summary>
        ///     移动sheet中所有合并区域
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="moveRowCount"></param>
        /// <param name="moveColCount"></param>
        public static void MoveMergedRegions(this ISheet sheet, int moveRowCount, int moveColCount = 0)
        {
            sheet.MoveMergedRegions(null, null, null, null, moveRowCount, moveColCount);
        }

        /// <summary>
        ///     移动指定区域内的合并区域
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="moveRowCount"></param>
        /// <param name="moveColCount"></param>
        public static void MoveMergedRegions(this ISheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol,
            int moveRowCount, int moveColCount = 0)
        {
            for (int i = 0; i < sheet.NumMergedRegions; i++)
            {
                CellRangeAddress range = sheet.GetMergedRegion(i);
                if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, range.FirstRow, range.LastRow,
                    range.FirstColumn, range.LastColumn, true))
                {
                    range.FirstRow += moveRowCount;
                    range.LastRow += moveRowCount;
                    range.FirstColumn += moveColCount;
                    range.LastColumn += moveColCount;
                }
            }
        }

        #endregion


        #region 图片

        #region 1.0 添加图片

        /// <summary>
        ///     添加图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="picInfo"></param>
        public static void AddPicture(this ISheet sheet, PictureInfo picInfo)
        {
            int pictureIdx = sheet.Workbook.AddPicture(picInfo.PictureData, PictureType.PNG);
            IClientAnchor anchor = sheet.Workbook.GetCreationHelper().CreateClientAnchor();
            anchor.Col1 = picInfo.MinCol;
            anchor.Col2 = picInfo.MaxCol;
            anchor.Row1 = picInfo.MinRow;
            anchor.Row2 = picInfo.MaxRow;
            anchor.Dx1 = picInfo.PicturesStyle.AnchorDx1;
            anchor.Dx2 = picInfo.PicturesStyle.AnchorDx2;
            anchor.Dy1 = picInfo.PicturesStyle.AnchorDy1;
            anchor.Dy2 = picInfo.PicturesStyle.AnchorDy2;
            anchor.AnchorType = AnchorType.MoveDontResize;
            IDrawing drawing = sheet.CreateDrawingPatriarch();
            IPicture pic = drawing.CreatePicture(anchor, pictureIdx);
            if (sheet is HSSFSheet)
            {
                var shape = (HSSFShape)pic;
                shape.FillColor = picInfo.PicturesStyle.FillColor;
                shape.IsNoFill = picInfo.PicturesStyle.IsNoFill;
                shape.LineStyle = picInfo.PicturesStyle.LineStyle;
                shape.LineStyleColor = picInfo.PicturesStyle.LineStyleColor;
                shape.LineWidth = (int)picInfo.PicturesStyle.LineWidth;
            }
            else if (sheet is XSSFSheet)
            {
                var shape = (XSSFShape)pic;
                shape.FillColor = picInfo.PicturesStyle.FillColor;
                shape.IsNoFill = picInfo.PicturesStyle.IsNoFill;
                shape.LineStyle = picInfo.PicturesStyle.LineStyle;
                //shape.LineStyleColor = picInfo.PicturesStyle.LineStyleColor;
                shape.LineWidth = picInfo.PicturesStyle.LineWidth;
            }
        }

        #endregion

        #region 1.1 获取图片信息

        /// <summary>
        ///     获取sheet中包含图片的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <returns></returns>
        public static List<PictureInfo> GetAllPictureInfos(this ISheet sheet)
        {
            return sheet.GetAllPictureInfos(null, null, null, null);
        }

        /// <summary>
        ///     获取sheet中指定区域包含图片的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <returns></returns>
        public static List<PictureInfo> GetAllPictureInfos(this ISheet sheet, int? minRow, int? maxRow, int? minCol,
            int? maxCol, bool onlyInternal = true)
        {
            if (sheet is HSSFSheet)
            {
                return GetAllPictureInfos((HSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            if (sheet is XSSFSheet)
            {
                return GetAllPictureInfos((XSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            throw new Exception("未处理类型，没有为该类型添加：GetAllPicturesInfos()扩展方法！");
        }

        #endregion

        #region 1.3 删除图片

        /// <summary>
        ///     清除sheet中的图片
        /// </summary>
        /// <param name="sheet"></param>
        public static void RemovePictures(this ISheet sheet)
        {
            sheet.RemovePictures(null, null, null, null);
        }

        /// <summary>
        ///     清除sheet中指定区域的图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        public static void RemovePictures(this ISheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol,
            bool onlyInternal = true)
        {
            if (sheet is HSSFSheet)
            {
                RemovePictures((HSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            else if (sheet is XSSFSheet)
            {
                RemovePictures((XSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            else
            {
                throw new Exception("未处理类型，没有为该类型添加：GetAllPicturesInfos()扩展方法！");
            }
        }

        #endregion

        #region 1.4 移动图片

        /// <summary>
        ///     移动sheet中所有图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="moveRowCount"></param>
        /// <param name="moveColCount"></param>
        public static void MovePictures(this ISheet sheet, int moveRowCount = 0, int moveColCount = 0)
        {
            sheet.MovePictures(null, null, null, null, true, moveRowCount, moveColCount);
        }

        /// <summary>
        ///     移动指定区域内的图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <param name="moveRowCount"></param>
        /// <param name="moveColCount"></param>
        public static void MovePictures(this ISheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol,
            bool onlyInternal = true,
            int moveRowCount = 0, int moveColCount = 0)
        {
            var shapeContainer = sheet.DrawingPatriarch as HSSFShapeContainer;
            if (null != shapeContainer)
            {
                IList<HSSFShape> shapeList = shapeContainer.Children;
                foreach (HSSFShape shape in shapeList)
                {
                    var anchor = shape.Anchor as IClientAnchor;
                    if (null != anchor)
                    {
                        if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2, anchor.Col1,
                            anchor.Col2, onlyInternal))
                        {
                            anchor.Row1 += moveRowCount;
                            anchor.Row2 += moveRowCount;
                            anchor.Col1 += moveColCount;
                            anchor.Col2 += moveColCount;
                        }
                    }
                }
            }
        }

        #endregion

        #region 3.0 实现（获取图片信息）

        /// <summary>
        ///     HSSFSheet获取指定区域包含图片的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <returns></returns>
        private static List<PictureInfo> GetAllPictureInfos(HSSFSheet sheet, int? minRow, int? maxRow, int? minCol,
            int? maxCol, bool onlyInternal)
        {
            var picturesInfoList = new List<PictureInfo>();

            var shapeContainer = sheet.DrawingPatriarch as HSSFShapeContainer;
            if (null != shapeContainer)
            {
                IList<HSSFShape> shapeList = shapeContainer.Children;
                foreach (HSSFShape shape in shapeList)
                {
                    if (shape is HSSFPicture && shape.Anchor is HSSFClientAnchor)
                    {
                        var picture = (HSSFPicture)shape;
                        var anchor = (HSSFClientAnchor)shape.Anchor;
                        if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2, anchor.Col1,
                            anchor.Col2, onlyInternal))
                        {
                            var picStyle = new PictureStyle
                            {
                                AnchorDx1 = anchor.Dx1,
                                AnchorDx2 = anchor.Dx2,
                                AnchorDy1 = anchor.Dy1,
                                AnchorDy2 = anchor.Dy2,
                                IsNoFill = picture.IsNoFill,
                                LineStyle = picture.LineStyle,
                                LineStyleColor = picture.LineStyleColor,
                                LineWidth = picture.LineWidth,
                                FillColor = picture.FillColor
                            };
                            picturesInfoList.Add(new PictureInfo(anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2,
                                picture.PictureData.Data, picStyle));
                        }
                    }
                }
            }

            return picturesInfoList;
        }

        /// <summary>
        ///     XSSFSheet获取指定区域包含图片的信息列表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <returns></returns>
        private static List<PictureInfo> GetAllPictureInfos(XSSFSheet sheet, int? minRow, int? maxRow, int? minCol,
            int? maxCol, bool onlyInternal)
        {
            var picturesInfoList = new List<PictureInfo>();

            List<POIXMLDocumentPart> documentPartList = sheet.GetRelations();
            foreach (POIXMLDocumentPart documentPart in documentPartList)
            {
                if (documentPart is XSSFDrawing)
                {
                    var drawing = (XSSFDrawing)documentPart;
                    List<XSSFShape> shapeList = drawing.GetShapes();
                    foreach (XSSFShape shape in shapeList)
                    {
                        if (shape is XSSFPicture)
                        {
                            var picture = (XSSFPicture)shape;
                            IClientAnchor anchor = picture.GetPreferredSize();

                            if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2,
                                anchor.Col1, anchor.Col2, onlyInternal))
                            {
                                var picStyle = new PictureStyle
                                {
                                    AnchorDx1 = anchor.Dx1,
                                    AnchorDx2 = anchor.Dx2,
                                    AnchorDy1 = anchor.Dy1,
                                    AnchorDy2 = anchor.Dy2,
                                    IsNoFill = picture.IsNoFill,
                                    LineStyle = picture.LineStyle,
                                    LineStyleColor = picture.LineStyleColor,
                                    LineWidth = picture.LineWidth,
                                    FillColor = picture.FillColor
                                };
                                picturesInfoList.Add(new PictureInfo(anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2,
                                    picture.PictureData.Data, picStyle));
                            }
                        }
                    }
                }
            }

            return picturesInfoList;
        }

        #endregion

        #region 3.1 实现（删除图片）

        /// <summary>
        ///     HSSFSheet清除指定区域的图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        private static void RemovePictures(HSSFSheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol,
            bool onlyInternal)
        {
            var shapeContainer = sheet.DrawingPatriarch as HSSFShapeContainer;
            if (null != shapeContainer)
            {
                IList<HSSFShape> shapeList = shapeContainer.Children;
                for (int i = 0; i < shapeList.Count; i++)
                {
                    HSSFShape shape = shapeList[i];
                    if (shape is HSSFPicture && shape.Anchor is HSSFClientAnchor)
                    {
                        var picture = (HSSFPicture)shape;
                        var anchor = (HSSFClientAnchor)shape.Anchor;
                        if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2, anchor.Col1,
                            anchor.Col2, onlyInternal))
                        {
                            shapeContainer.RemoveShape(shape);
                        }
                    }
                }
            }
        }

        /// <summary>
        ///     XSSFSheet清除指定区域的图片
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        private static void RemovePictures(XSSFSheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol,
            bool onlyInternal)
        {
            List<POIXMLDocumentPart> documentPartList = sheet.GetRelations();
            foreach (POIXMLDocumentPart documentPart in documentPartList)
            {
                if (documentPart is XSSFDrawing)
                {
                    var drawing = (XSSFDrawing)documentPart;
                    List<XSSFShape> shapeList = drawing.GetShapes();

                    for (int i = 0; i < shapeList.Count; i++)
                    {
                        XSSFShape shape = shapeList[i];
                        if (shape is XSSFPicture)
                        {
                            var picture = (XSSFPicture)shape;
                            IClientAnchor anchor = picture.GetPreferredSize();

                            if (CellExtensions.IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2,
                                anchor.Col1, anchor.Col2, onlyInternal))
                            {
                                throw new NotImplementedException("XSSFSheet未实现ClearPictures()方法！");
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #endregion
    }
}
